package ca.krakenpower.kvoxels;

public class BoundingBox {
	
	public Vector3 a, b;
	
	public BoundingBox(Vector3 a, double size) {
		this.a = a;
		this.b = Vector3.get(a.x + size, a.y + size, a.z + size);
	}
	
	public boolean contains(Vector3 p) {
		if (
				p.x >= a.x && p.x <= b.x &&
				p.y >= a.y && p.y <= b.y &&
				p.z >= a.z && p.z <= b.z) {
			return true;
		}
		
		return false;
	}
	
	public double sideLength() {
		return b.x - a.x;
	}
	
	public BoundingBox[] getOctants() {
		BoundingBox[] octants = new BoundingBox[8];
		double size = sideLength() / 2;
		
		octants[0] = new BoundingBox(a, size);
		octants[1] = new BoundingBox(Vector3.get(a.x + size, a.y, a.z), size);
		octants[2] = new BoundingBox(Vector3.get(a.x, a.y + size, a.z), size);
		octants[3] = new BoundingBox(Vector3.get(a.x + size, a.y + size, a.z), size);
		octants[4] = new BoundingBox(Vector3.get(a.x, a.y, a.z + size), size);
		octants[5] = new BoundingBox(Vector3.get(a.x + size, a.y, a.z + size), size);
		octants[6] = new BoundingBox(Vector3.get(a.x, a.y + size, a.z + size), size);
		octants[7] = new BoundingBox(Vector3.get(a.x + size, a.y + size, a.z + size), size);
		
		return octants;
	}
	
	public double[] intersect(Vector3 origin, Vector3 direction) {
		// http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/
		
		Vector3 invdir = Vector3.get(1 / direction.x, 1 / direction.y, 1 / direction.z);
		double tmin, tmax, tymin, tymax, tzmin, tzmax;
		
		if (invdir.x >= 0) {
			tmin = (a.x - origin.x) * invdir.x;
			tmax = (b.x - origin.x) * invdir.x; 
		} else {
			tmin = (b.x - origin.x) * invdir.x;
			tmax = (a.x - origin.x) * invdir.x;
		}
		
		if (invdir.y >= 0) {
			tymin = (a.y - origin.y) * invdir.y;
			tymax = (b.y - origin.y) * invdir.y; 
		} else {
			tymin = (b.y - origin.y) * invdir.y;
			tymax = (a.y - origin.y) * invdir.y;
		}
		
		if ((tmin > tymax) || (tymin > tmax)) {
			return null;
		}
		if (tymin > tmin) {
			tmin = tymin;
		}
		if (tymax < tmax) {
			tmax = tymax;
		}
		
		if (invdir.z >= 0) {
			tzmin = (a.z - origin.z) * invdir.z;
			tzmax = (b.z - origin.z) * invdir.z; 
		} else {
			tzmin = (b.z - origin.z) * invdir.z;
			tzmax = (a.z - origin.z) * invdir.z;
		}
		
		if ((tmin > tzmax) || (tzmin > tmax)) {
			return null;
		}
		if (tzmin > tmin) {
			tmin = tzmin;
		}
		if (tzmax < tmax) {
			tmax = tzmax;
		}
		
		double[] intersects = new double[2];
		
		intersects[0] = Math.max(0, tmin);
		intersects[1] = Math.max(0, tmax);
		
		return intersects;
	}

}
